package com.tanklab.signature.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.tanklab.signature.common.util.*;
import com.tanklab.signature.common.util.sm2Util.Sm2;
import com.tanklab.signature.ds.req.UserLoginReq;
import com.tanklab.signature.ds.req.UserProfileUpdateReq;
import com.tanklab.signature.ds.req.UserRegisterReq;
import com.tanklab.signature.ds.resp.CommonResp;
import com.tanklab.signature.entity.Student;
import com.tanklab.signature.entity.Teacher;
import com.tanklab.signature.entity.User;
import com.tanklab.signature.entity.UserSignature;
import com.tanklab.signature.mapper.StudentMapper;
import com.tanklab.signature.mapper.TeacherMapper;
import com.tanklab.signature.mapper.UserMapper;
import com.tanklab.signature.mapper.UserSignatureMapper;
import com.tanklab.signature.service.FileStorageService;
import com.tanklab.signature.service.SignatureStorageService;
import com.tanklab.signature.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.tanklab.signature.eth.ChainConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private TeacherMapper teacherMapper;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private SignatureStorageService signatureStorageService;

    @Value("${signature.upload-dir:./uploads/signatures/}")
    private String signatureUploadDir;

    @Autowired
    private ChainUtils chainUtils;

    @Autowired
    private UserSignatureMapper userSignatureMapper;

    // Deprecated
    @Override
    public CommonResp login(UserLoginReq userloginreq){//加解密登录
        CommonResp userloginresp = new CommonResp();//返回体

        String KeyPairsFilePath = Constant.userKeyPairsTxt;
        String CryptoFilePath = Constant.userInfoTxt;

        String publicKey = userloginreq.getPublicKey().substring(2);
        String username = userloginreq.getUser_name();//密文账号
        String userpswd = userloginreq.getUser_pswd();//密文密码

        String key = FileUtil.findLine(publicKey,KeyPairsFilePath);//找到公私钥对
        String[] keys = null;
        String privateKey = null;
        String base64publicKey = null;
        if (key != null) {
            keys = key.split("\t");
            privateKey = keys[1];//获得私钥
            base64publicKey = keys[2];//获得base64公钥
        }
        String loginName=null;
        String password=null;
        try {
            loginName = Sm2.Decrypt(username, privateKey);
            password = Sm2.Decrypt(userpswd, privateKey);//密文解密为明文
        }catch(Exception e){
            System.out.println("Wrong decrypt");
        }

        if (!CommonUtil.isValidPhoneNumber(username)){
            userloginresp.setRet(ResultCode.LOGIN_FAIL_PHONENUM);
            return userloginresp;
        }

        String inforLine = loginName + "\t" + password;//明文
        if(FileUtil.countLine(inforLine,CryptoFilePath,1)==0)//还未注册
        {
            userloginresp.setRet(ResultCode.LOGIN_FAIL_NOREGISTER);
            return userloginresp;
        }
        else {
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("user_name",username);
            List<User> users = userMapper.selectList(wrapper);
            if (users.size() != 1){
                userloginresp.setRet(ResultCode.LOGIN_FAIL);
                return userloginresp;
            } else {
                User user = users.get(0);
                if (user.getUser_pswd().compareTo(userpswd) == 0 && user.getUser_name().compareTo(loginName) == 0){
                    userloginresp.setRet(ResultCode.SUCCESS);
                    JSONObject data = new JSONObject();
                    data.put("token",user.getToken());
                    data.put("authority",user.getAuthority());
                    data.put("url",user.getAvatarUrl());
                    userloginresp.setData(data);
                }else {
                    userloginresp.setRet(ResultCode.PSWD_ERROR);
                    return userloginresp;
                }
            }
        }
        return userloginresp;
    }


    // Deprecated
    @Override
    public CommonResp register(UserRegisterReq userregisterreq) {
        CommonResp userregisterresp = new CommonResp();//返回体

        String KeyPairsFilePath = Constant.userKeyPairsTxt;
        String CryptoFilePath = Constant.userInfoTxt;

        String publicKey = userregisterreq.getPublicKey().substring(2);
        String username = userregisterreq.getUser_name();//密文账号
        String userpswd = userregisterreq.getUser_pswd();//密文密码
        String url = userregisterreq.getUrl();

        String key = FileUtil.findLine(publicKey, KeyPairsFilePath);//找到公私钥对
        String[] keys = null;
        String privateKey = null;
        String base64publicKey = null;
        if (key != null) {
            keys = key.split("\t");
            privateKey = keys[1];//获得私钥
            base64publicKey = keys[2];//获得base64公钥
        }
        String loginName = null;
        String password = null;
        try {
            loginName = Sm2.Decrypt(username, privateKey);
            password = Sm2.Decrypt(userpswd, privateKey);//密文解密为明文
        } catch (Exception e) {
            System.out.println("Wrong decrypt");
        }

        if (!CommonUtil.isValidPhoneNumber(username)) {
            userregisterresp.setRet(ResultCode.REGISTER_FAIL_PHONENUM);
            userregisterresp.setData("Wrong phone number");
            return userregisterresp;
        }

        String inforLine = loginName + "\t" + password;//明文
        if (FileUtil.countLine(inforLine, CryptoFilePath, 1) == 0)//还未注册
        {
            String cryptLine = inforLine+"\t"+publicKey+"\t"+privateKey+"\t"+base64publicKey+"\t"+loginName+"\t"+password;
            //手机号+密码+钥对+密文对
            FileUtil.writeByLine(CryptoFilePath,cryptLine);//隐私信息存入本地
            User user = new User();
            user.setUser_name(loginName);
            user.setUser_pswd(userpswd);
            user.setAuthority(userregisterreq.getAuthority());
            user.setAvatarUrl(url);
//            userMapper.insert(user);
            if(userregisterreq.getAuthority()==0){//学生
                Student student = new Student();
                student.setName_student(loginName);
                student.setSignature_student(userregisterreq.getSignature());
                student.setNum_request(0);
                synchronized (this){
                    userMapper.insert(user);
                    studentMapper.insert(student);
                }
            }else if(userregisterreq.getAuthority()==1){//老师
                Teacher teacher = new Teacher();
                teacher.setName_teacher(loginName);
                teacher.setSignature_teacher(userregisterreq.getSignature());
                synchronized (this){
                    userMapper.insert(user);
                    teacherMapper.insert(teacher);
                }
            }
            else{
                userregisterresp.setRet(ResultCode.REGISTER_FAIL);
                userregisterresp.setData("authority error");
                return userregisterresp;
            }
        } else {//已经注册过了
            userregisterresp.setRet(ResultCode.REGISTER_FAIL_ALREADY);
            return userregisterresp;
        }
        return userregisterresp;
    }

    @Override
    @Transactional
    public boolean updateUserAvatar(String openid, String avatarUrl) {
        // 检查用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openid", openid);
        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            return false;
        }

        // 如果用户之前已有头像，删除旧头像文件
        if (user.getAvatarUrl() != null && !user.getAvatarUrl().isEmpty()) {
            fileStorageService.deleteAvatar(user.getAvatarUrl());
        }

        // 更新用户头像URL
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("openid", openid);

        User updateUser = new User();
        updateUser.setAvatarUrl(avatarUrl);

        int updated = userMapper.update(updateUser, updateWrapper);

        return updated > 0;
    }

    @Override
    @Transactional
    public CommonResp updateUserProfile(UserProfileUpdateReq profileReq, String openid) {
        CommonResp resp = new CommonResp();

        // 检查用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openid", openid);
        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            resp.setRet(ResultCode.USER_NOT_EXIST);
            resp.setMsg("用户不存在");
            return resp;
        }

        // 更新用户信息
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("openid", openid);

        User updateUser = new User();
        updateUser.setUser_name(profileReq.getName());
        String identity = profileReq.getIdentity();
        if (identity.equals("审批者")) {
            updateUser.setAuthority(100);
        } else if (identity.equals("申请者")) {
            updateUser.setAuthority(0);
        }


        int updated = userMapper.update(updateUser, updateWrapper);

        if (updated > 0) {
            // 构造返回数据
            JSONObject data = new JSONObject();
            data.put("name", profileReq.getName());
            data.put("identity", profileReq.getIdentity());

            resp.setRet(ResultCode.SUCCESS);
            resp.setMsg("用户资料更新成功");
            resp.setData(data);
        } else {
            resp.setRet(ResultCode.ERROR);
            resp.setMsg("用户资料更新失败");
        }

        return resp;
    }

    @Override
    public CommonResp getUserProfile(String openid) {
        CommonResp resp = new CommonResp();

        // 检查用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openid", openid);
        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            resp.setRet(ResultCode.USER_NOT_EXIST);
            resp.setMsg("用户不存在");
            return resp;
        }

        // 构造返回数据
        JSONObject data = new JSONObject();
        data.put("user_name", user.getUser_name());
        data.put("avatarUrl", user.getAvatarUrl());

        // 根据authority字段确定身份
        String identity = "";
        if (user.getAuthority() == 0) {
            identity = "申请者";
        } else if (user.getAuthority() >= 100) {
            identity = "审批者";
        }
        data.put("identity", identity);

        resp.setRet(ResultCode.SUCCESS);
        resp.setMsg("获取用户信息成功");
        resp.setData(data);

        return resp;
    }

    @Override
    @Transactional
    public CommonResp uploadSignature(String openid, String signatureUrl) {
        CommonResp resp = new CommonResp();

        // 查询用户是否存在
        QueryWrapper<User> userQuery = new QueryWrapper<>();
        userQuery.eq("openid", openid);
        User user = userMapper.selectOne(userQuery);

        if (user == null) {
            resp.setRet(ResultCode.USER_NOT_EXIST);
            resp.setMsg("用户不存在");
            return resp;
        }

        try {
            // 如果用户之前已有签名，删除旧签名
            if (user.getSignatureUrl() != null && !user.getSignatureUrl().isEmpty()) {
                signatureStorageService.deleteSignature(user.getSignatureUrl());
            }

            // 计算签名图片哈希值
            String signatureHash = calculateSignatureHash(signatureUrl);

            // 上链
            String txId = chainUtils.sendHashToChain(signatureHash,"signatureHash"); // 临时处理，使用默认值

            // 1. 将所有该用户的签名设置为非活跃
            QueryWrapper<UserSignature> signatureQuery = new QueryWrapper<>();
            signatureQuery.eq("user_openid", openid);
            signatureQuery.eq("is_active", true);

            UserSignature existingActiveSignature = userSignatureMapper.selectOne(signatureQuery);
            if (existingActiveSignature != null) {
                existingActiveSignature.setIsActive(false);
                userSignatureMapper.updateById(existingActiveSignature);
            }

            // 2. 创建新的签名记录
            UserSignature newSignature = new UserSignature();
            newSignature.setUserOpenid(openid);
            newSignature.setSignatureUrl(signatureUrl);
            newSignature.setSignatureHash(signatureHash);
            newSignature.setSignatureTxId(txId);
            newSignature.setIsActive(true);
            newSignature.setCreatedTime(TimeUtils.getCurrentTime());

            userSignatureMapper.insert(newSignature);

            // 3. 同时更新 User 表中的签名URL
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("openid", openid)
                    .set("signature_url", signatureUrl)
                    .set("signature_hash", signatureHash)
                    .set("signature_tx_id", txId);

            boolean updated = this.update(updateWrapper);

            if (updated) {
                JSONObject data = new JSONObject();
                data.put("signatureUrl", signatureUrl);
                data.put("signatureHash", signatureHash);
                data.put("txId", txId);
                data.put("signatureId", newSignature.getId());

                resp.setRet(ResultCode.SUCCESS);
                resp.setMsg("签名上传成功");
                resp.setData(data);
            } else {
                resp.setRet(ResultCode.ERROR);
                resp.setMsg("签名上传失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
            resp.setRet(ResultCode.ERROR);
            resp.setMsg("签名上传失败：" + e.getMessage());
        }

        return resp;
    }

    /**
     * 计算签名图片的哈希值
     */
    private String calculateSignatureHash(String signatureUrl) throws Exception {
        // 从URL中提取文件名
        String filename = signatureUrl.substring(signatureUrl.lastIndexOf("/") + 1);
        Path filePath = Paths.get(signatureUploadDir, filename);

        // 读取文件内容并计算哈希
        byte[] fileContent = Files.readAllBytes(filePath);
        return HashUtil.hash_func(new String(fileContent), "MD5");
    }

    @Override
    public CommonResp getUserSignature(String openid) {
        CommonResp resp = new CommonResp<>();

        // 检查用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openid", openid);
        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            resp.setRet(ResultCode.USER_NOT_EXIST);
            resp.setMsg("用户不存在");
            return resp;
        }

        // 检查用户是否已上传签名
        if (user.getSignatureUrl() == null || user.getSignatureUrl().isEmpty()) {
            resp.setRet(ResultCode.DATA_NOT_EXIST);
            resp.setMsg("用户尚未上传签名");
            return resp;
        }

        // 构造返回数据
        JSONObject data = new JSONObject();
        data.put("signatureUrl", user.getSignatureUrl());
        data.put("signatureHash", user.getSignatureHash());
        data.put("signatureTxId", user.getSignatureTxId());
        data.put("user_name", user.getUser_name());

        // 判断用户类型
        String userType = user.getAuthority() >= 100 ? "审批者" : "申请者";
        data.put("userType", userType);

        resp.setRet(ResultCode.SUCCESS);
        resp.setMsg("获取用户签名成功");
        resp.setData(data);

        return resp;
    }

    @Override
    public UserSignature getActiveSignature(String openid) {
        QueryWrapper<UserSignature> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_openid", openid)
                .eq("is_active", true);
        return userSignatureMapper.selectOne(queryWrapper);
    }

    @Override
    public List<UserSignature> getUserSignatureHistory(String openid) {
        QueryWrapper<UserSignature> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_openid", openid)
                .orderByDesc("created_time");
        return userSignatureMapper.selectList(queryWrapper);
    }

}

